package com.hclc.yxb.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.hclc.config.context.exception.AuthenticationException;
import com.hclc.entity.dto.UserRedisDto;
import com.hclc.entity.dvo.MenuTreeDvo;
import com.hclc.entity.dvo.MenuTreeMetaDvo;
import com.hclc.entity.model.SysUserModel;
import com.hclc.entity.model.contans.ApiConst;
import com.hclc.entity.model.enums.HiddenEnum;
import com.hclc.util.bean.BeanCopyUtils;
import com.hclc.util.json.JsonUtil;
import com.hclc.yxb.dto.SysUserInfoDto;
import com.hclc.yxb.dvo.SysUserInfoDvo;
import com.hclc.yxb.mapper.SysMenuMapper;
import com.hclc.yxb.mapper.SysRoleMapper;
import com.hclc.yxb.mapper.SysRoleMenuMapper;
import com.hclc.yxb.mapper.SysUserRoleMapper;
import com.hclc.yxb.model.*;
import com.hclc.yxb.service.ConsoleUserInfoService;
import com.hclc.yxb.util.MenuTreeToolUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * @ClassName PwlUserInfoServiceImpl
 * @Author: yurj
 * @Mail：1638234804@qq.com
 * @Date: Create in 15:36 2020/8/22
 * @version: 1.0
 */
@Service
@Slf4j
public class ConsoleUserInfoServiceImpl implements ConsoleUserInfoService {

    @Autowired
    private SysRoleMapper sysRoleMapper;

    @Autowired
    private SysUserRoleMapper sysUserRoleMapper;

    @Autowired
    private SysRoleMenuMapper sysRoleMenuMapper;

    @Autowired
    private SysMenuMapper sysMenuMapper;


    /**
     * 后台管理员登录
     *
     * @param userName
     * @param userPass
     * @return com.hclc.pwl.dto.UserInfoDto
     * @author yurj
     * @mail 1638234804@qq.com
     * @version 1.0
     * @date 2020/8/22 15:39
     */
    @Override
    public UserRedisDto selectUserInfo(HttpServletRequest request, HttpServletResponse response, String userName, String userPass) {
        Subject subject = SecurityUtils.getSubject();
        UsernamePasswordToken usernamePasswordToken = new UsernamePasswordToken(userName, userPass);
        subject.login(usernamePasswordToken);
        SysUserModel sysUserModel = (SysUserModel) SecurityUtils.getSubject().getPrincipal();
        // 用户角色id集
        List<String> roleIds = selectUserRoleIds(sysUserModel.getId());
        // 用户角色对应菜单id集
        List<String> roleMenus = selectRoleMenuIds(roleIds);
        // 用户角色路由集
        List<MenuTreeDvo> menuTree = selectUserMenuRouting(roleMenus);
        // 组装用户返回对象
        SysUserInfoDvo SysUserInfoDvo = new SysUserInfoDvo();
        SysUserInfoDvo.setSysUserModel(sysUserModel);
        SysUserInfoDvo.setMenuTree(menuTree);
        // 返回对象
        UserRedisDto<SysUserInfoDto> redisDto = new UserRedisDto<>();
        SysUserInfoDto userInfoDto = new SysUserInfoDto();
        userInfoDto.setId(sysUserModel.getId());
        userInfoDto.setUserName(sysUserModel.getUserName());
        userInfoDto.setUserLogo(sysUserModel.getUserLogo());
        userInfoDto.setDeptId(sysUserModel.getDeptId());
        userInfoDto.setMenuTree(menuTree);
        redisDto.setData(userInfoDto);
        redisDto.setToken(String.valueOf(subject.getSession().getId()));
        return redisDto;
    }


    /**
     * 获取用户角色id集
     *
     * @param userId
     * @return java.util.List<java.lang.String>
     * @author yurj
     * @mail 1638234804@qq.com
     * @version 1.0
     * @date 2020/8/19 11:08
     */
    private List<String> selectUserRoleIds(String userId) {
        // 用户角色集合
        List<String> roleIds = sysUserRoleMapper.selectList(new QueryWrapper<SysUserRoleModel>()
                .lambda()
                .eq(SysUserRoleModel::getEnable, ApiConst.ENABLE_TRUE)
                .eq(SysUserRoleModel::getUserId, userId)
        ).parallelStream().map(s -> s.getRoleId()).collect(Collectors.toList());
        if (CollectionUtils.isEmpty(roleIds)) {
            throw new AuthenticationException("用户没有对应角色");
        }
        return roleIds;
    }

    /**
     * 获取用户菜单id集
     *
     * @param roleIds
     * @return java.util.List<java.lang.String>
     * @author yurj
     * @mail 1638234804@qq.com
     * @version 1.0
     * @date 2020/8/19 11:14
     */
    private List<String> selectRoleMenuIds(List<String> roleIds) {
        // 角色对应菜单id集
        List<String> roleMenus = sysRoleMenuMapper.selectList(new QueryWrapper<SysRoleMenuModel>()
                .lambda()
                .eq(SysRoleMenuModel::getEnable, ApiConst.ENABLE_TRUE)
                .in(SysRoleMenuModel::getRoleId, roleIds)
        ).parallelStream().map(s -> s.getMenuId()).collect(Collectors.toList());
        if (CollectionUtils.isEmpty(roleMenus)) {
            throw new AuthenticationException("用户没有对应菜单");
        }
        return roleMenus;
    }

    /**
     * 获取用户菜单路由树
     *
     * @param roleMenus
     * @return java.util.List<com.hclc.pwl.dvo.MenuTreeDvo>
     * @author yurj
     * @mail 1638234804@qq.com
     * @version 1.0
     * @date 2020/8/19 11:08
     */
    private List<MenuTreeDvo> selectUserMenuRouting(List<String> roleMenus) {
        // 父级菜单
        List<MenuTreeDvo> rootList = new ArrayList<>();
        // 子级菜单
        List<MenuTreeDvo> bodyList = new ArrayList<>();
        // 获取角色对应菜单信息列表
        sysMenuMapper.selectList(new QueryWrapper<SysMenuModel>()
                .lambda()
                .eq(SysMenuModel::getEnable, ApiConst.ENABLE_TRUE)
                .in(SysMenuModel::getId, roleMenus)
                .orderByAsc(SysMenuModel::getSort)
        ).stream().forEach(s -> {
            MenuTreeDvo menuTreeBean = new MenuTreeDvo();
            menuTreeBean.setName(StringUtils.EMPTY);
            menuTreeBean.setRedirect(StringUtils.EMPTY);
            menuTreeBean.setPermName(StringUtils.EMPTY);
            try {
                BeanCopyUtils.copyProperties(s, menuTreeBean);
            } catch (BeansException e) {
                log.error("查询用户菜单列表赋值异常,source:{},target:{}", s, menuTreeBean, e);
            }
            menuTreeBean.setHidden(HiddenEnum.YES.equals(s.getHidden()) ? true : false);
            if (StringUtils.isNotBlank(s.getMeta())) {
                menuTreeBean.setMeta(JsonUtil.toObject(s.getMeta(), MenuTreeMetaDvo.class));
            }
            // 父级id为0则为顶级菜单
            if (Objects.equals(s.getParentId(), ApiConst.ZERO_STRING)) {
                rootList.add(menuTreeBean);
            } else {
                bodyList.add(menuTreeBean);
            }
        });
        // 生成用户管理系统路由集
        MenuTreeToolUtils menuTreeToolUtils = new MenuTreeToolUtils(rootList, bodyList);
        return menuTreeToolUtils.getTree();
    }

    /**
     * 获取用户id权限字符串
     *
     * @param roleIds
     * @return java.lang.String
     * @author yurj
     * @mail 1638234804@qq.com
     * @version 1.0
     * @date 2020/8/19 11:17
     */
    private String selectUserRoleNameStr(List<String> roleIds) {
        // 用户权限集合
        String roleNameStr = sysRoleMapper.selectList(new QueryWrapper<SysRoleModel>()
                .lambda()
                .eq(SysRoleModel::getEnable, ApiConst.ENABLE_TRUE)
                .in(SysRoleModel::getId, roleIds)
        ).parallelStream().map(s -> s.getRoleName()).collect(Collectors.joining(ApiConst.SYMBOL_COMMA));
        return roleNameStr;
    }

}
